
#include <testpackage.h>
#include "package.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

static const char *convert_path(char *str) {
	uint32_t p = 0;

	while (str[p] != 0) {
		if (str[p] == '\\') str[p] = '/';
		p += 1;
	}
	return str;
}

static jstatus_t parse_time_limit(struct package *package, char *p) {
	uint32_t data;

	if (sscanf(p, "time_limit %d", &data) != 1) 
		return JSTATUS_BAD_CONFIG;
	package->time_limit = data;
	return JSTATUS_SUCCESS;
}

static jstatus_t parse_memory_limit(struct package *package, char *p) {
	uint32_t data;

	if (sscanf(p, "memory_limit %d", &data) != 1) 
		return JSTATUS_BAD_CONFIG;
	package->memory_limit = data;
	return JSTATUS_SUCCESS;
}

static jstatus_t parse_spj(struct package *package, char *p, int32_t *buffer_offset) {
	char *pb = package->temp_buffer + *buffer_offset;

	if (package->testcase_count != 0)
		return JSTATUS_BAD_CONFIG;
	if (sscanf(p, "spj %[^\n^\r]", pb) != 1) 
		return JSTATUS_BAD_CONFIG;
	package->has_spj = 1;
	*buffer_offset += strlen(pb) + 1;
	package->temp_buffer[*buffer_offset - 1] = 0;
	package->spj_prefix = convert_path(pb);
	return JSTATUS_SUCCESS;
}

static jstatus_t parse_testcase_spj(struct package *package, char *p, int32_t *buffer_offset) {
	char *pb = package->temp_buffer + *buffer_offset;
	struct list_item *item;

	if (package->has_spj == 0) 
		return JSTATUS_SUCCESS;
	if (sscanf(p, "testcase_spj %[^\n^\r]", pb) != 1) 
		return JSTATUS_BAD_CONFIG;
	item = list_new_item((void *)pb, NULL);
	list_insert(&package->spj_key_list, item);
	package->spj_key_count += 1;
	*buffer_offset += strlen(pb) + 1;
	package->temp_buffer[*buffer_offset - 1] = 0;
	return JSTATUS_SUCCESS;
}

static jstatus_t parse_testcase(struct package *package, char *p, int32_t *buffer_offset) {
	char *pb = package->temp_buffer + *buffer_offset, *pb2;
	int length;
	struct list_item *item;

	if (package->has_spj == 1) 
		return JSTATUS_BAD_CONFIG;
	if (sscanf(p, "testcase %[^|]", pb) != 1) 
		return JSTATUS_BAD_CONFIG;
	pb2 = pb + strlen(pb) + 1;
	if (sscanf(p, "testcase %[^|]|%[^\n^\r]", pb, pb2) != 2) 
		return JSTATUS_BAD_CONFIG;
	package->temp_buffer[*buffer_offset + strlen(pb)] = 0;
	length = strlen(pb) + strlen(pb2) + 1;
	item = list_new_item((void *)convert_path(pb), (void *)convert_path(pb2));
	list_insert(&package->testcase_list, item);
	package->testcase_count += 1;
	*buffer_offset += length + 1;
	package->temp_buffer[*buffer_offset - 1] = 0;
	return JSTATUS_SUCCESS;
}

jstatus_t config_parse(struct package *package, char *config_data, size_t config_size) {
	char *p;
	int32_t buffer_offset = 0;
	jstatus_t st;

	p = config_data;
	while (p - config_data < config_size) {
#ifndef _strcmp
#undef _strcmp
#define _strcmp(s1, s2) strncmp(s1, s2, strlen(s2))
#endif
		if (_strcmp(p, "time_limit") == 0) {
			st = parse_time_limit(package, p);
		} else if (_strcmp(p, "memory_limit") == 0) {
			st = parse_memory_limit(package, p);
		} else if (_strcmp(p, "spj") == 0) {
			st = parse_spj(package, p, &buffer_offset);
		} else if (_strcmp(p, "testcase_spj") == 0) {
			st = parse_testcase_spj(package, p, &buffer_offset);
		} else if (_strcmp(p, "testcase") == 0) {
			st = parse_testcase(package, p, &buffer_offset);
		} else if (_strcmp(p, "\n") == 0) {
			st = JSTATUS_SUCCESS;
		} else {
			st = JSTATUS_BAD_CONFIG;
		}
#ifdef _strcmp
#undef _strcmp
#endif
		if (!JSUCCESS(st)) 
			return st;
		p = strchr(p, '\n');
		if (p == NULL) break;
		p += 1;
	}
	return JSTATUS_SUCCESS;
}
